package subumbo.micro.controller
{
	import flash.display.DisplayObject;
	import flash.display.DisplayObjectContainer;
	import flash.display.Sprite;
	import flash.display.StageAlign;
	import flash.display.StageScaleMode;
	import flash.events.Event;
	
	import subumbo.micro.model.Model;

	public class Application extends Sprite
	{
		protected var _model:Model;
		protected var _container:DisplayObjectContainer;
		protected var _bg:DisplayObject;
		private var _centre:EventCentre;
	
		/**
		 * Added is called when added to stage.
		 * Override this method to write custom application initialization code.
		 * Ensure super gets called before additional code is executed.
		 * 
		 * @param e
		 * 
		 */		
		protected function added(e:Event):void
		{
			//trace("here");
			this.removeEventListener(Event.ADDED_TO_STAGE, added);
			
			stage.scaleMode = StageScaleMode.NO_SCALE;
			stage.align = StageAlign.TOP_LEFT;
			
			_centre.addEventListener(ApplicationEvent.MODEL_CACHED, applicationComplete);
			stage.addEventListener(Event.RESIZE, resize);
		}
		
		
		/**
		 * 
		 * This method is called when the data is cached in the Model class
		 * It activates the frontcontroller and calls the bind method on each Component 
		 * and then calls resize on the application.
		 * 
		 * Ensure that super gets called when overriden
		 * 
		 * @param e 
		 * 
		 */		
		protected function applicationComplete(e:ApplicationEvent):void
		{
			_centre.removeEventListener(ApplicationEvent.MODEL_CACHED, applicationComplete);
			_centre.addEventListener(ApplicationEvent.CONTROL, onControl);
			_centre.dispatch(new ApplicationEvent(ApplicationEvent.BIND));
			resize(null); 
		}
		
		
		
		/**
		 * Handles the front control of the application. Gets called by ApplicationEvent.CONTROL, updates the model 
		 * and dispatches an UPDATE Event to the View Components 
		 * @param e type CONTROL with data 
		 * 
		 */		
		private function onControl(e:ApplicationEvent):void
		{
			_model.update(e.data);
			_centre.dispatch(new ApplicationEvent(ApplicationEvent.UPDATE, e.data));
		}
		
		
		
		/**
		 * 
		 * Pass an Custom Object that holds your application data.
		 * This object is called ModelLocator by convention.
		 * 
		 * This method should be called in the overridden added method of the document class.
		 * 
		 * @param decorator the custom model class that implements IModel. Class is named ModelLocator by convention.
		 * 
		 */		
		protected function initModel(decorator:Object):void
		{
			_model = Model.instance;
			_model.init( decorator);
		}
		
		
		/**
		 * 
		 * @param bg is the application background Sprite
		 * @param container is the container that will be centered according to its width.
		 * 
		 * This method should be called in the overridden added method of the document class
		 * 
		 */		
		protected function initView(bg:DisplayObject, container:DisplayObjectContainer):void
		{
			_bg = bg;
			_container = container;
			this.addChild(_bg);
			this.addChild(_container);	
		}
		
		
		/**
		 * 
		 * Method is called on stage resize.
		 * 
		 * @param e:Event.RESIZE
		 * 
		 */		
		protected function resize(e:Event):void
		{
			_bg.width = stage.stageWidth;
			_bg.height = stage.stageHeight;
			_container.x = (stage.stageWidth / 2) - (_container.width / 2);
		}
		
		
		static private var _instance:Application;
		
		/**
		 * Singleton: Use "DocumentClassName".insctance to access the get the instance
		 * @return  
		 * 
		 */		
		static public function get insctance():Application
		{
			return _instance;
		}
		
		/**
		 * Contructor is not needed in child class 
		 */		
		public function Application()
		{
			init();
		}
		
		/**
		 * called on startup, add event listsener for ADDED_TO_STAGE. Don't override. 
		 */		
		public function init():void
		{
			_instance = this;
			_centre = EventCentre.instance;
			this.addEventListener(Event.ADDED_TO_STAGE, added);
		}
	}
}